/**************************************************************************************************
* Title: SumRenderManager.h
* Author: Gael Huber
* Description: Handles entirety of rendering subsystem.
**************************************************************************************************/
#ifndef __SUMRENDERMANAGER_H__
#define __SUMRENDERMANAGER_H__

#include <d3d11.h>
#include <D3DX11.h>
#include <D3DX10.h>
#include <D3Dcompiler.h>
#include "SumSingleton.h"
#include "SumRenderWindow.h"
#include "SumJobManager.h"
#include "SumCriticalSection.h"
#include "SumVertex.h"
#include "SumMesh.h"
#include "SumWVPMatrix.h"

//TEMP
#include "SumTimer.h"

class RenderManager : public Singleton<RenderManager> {
public:
	RenderManager(void);	// Constructor
	virtual ~RenderManager(void);	// Destructor

	// Get singleton
	inline static RenderManager& getSingleton(void)
	{
		assert(singleton);
		return *singleton;
	}
	// Get singleton pointer
	inline static RenderManager* getSingletonPtr(void)
	{
		return singleton;
	}

	void startUp(int nCmdShow);		// Initialize render manager
	void shutDown(void);	// Shut down render manager

	// Rendering methods
	void renderScene(void);		// Render the current scene
	HRESULT createBuffer(D3D11_BUFFER_DESC* bd, D3D11_SUBRESOURCE_DATA* initData, ID3D11Buffer** buffer);	// Create a data buffer

	// TEMP CODE
	Mesh mesh;
public:
	// Static method used as a wrapper for kicking off rendering
	static void kickRender(void* p);

private:
	// Initialization methods
	void initDirect3D(void);	// Initialize Direct3D
	void initPipeline(void);	// Initialize the rendering pipeline
	
	HRESULT compileShaderFromFile(WCHAR* filename, LPCSTR entryPoint, LPCSTR shaderModel, ID3DBlob** blobOut);	// Compile a shader given a filename

	// ShBuffer functions
	template <class T>
	HRESULT createConstantBuffer(ID3D11Buffer** ppCB);	// Create a constant buffer

	HRESULT createVertexShader(LPCWSTR pFile, LPCSTR pFunctionName, ID3D11VertexShader** ppShaderOut);		// Compile a vertex shader from file
	HRESULT createComputeShader(LPCWSTR pFile, LPCSTR pFunctionName, ID3D11ComputeShader** ppShaderOut);	// Compile a compute shader from file

private:	
	RenderWindow* window;	// Window into which simulation will be rendered
	IDXGISwapChain* swapChain;	// Swap chain interface
	D3D_DRIVER_TYPE driverType;	// Driver information
	D3D_FEATURE_LEVEL featureLevel;	// Feature level
	ID3D11Device* device;	// Direct3D device
	ID3D11DeviceContext* deviceContext;	// Direct3D device context
	ID3D11RenderTargetView* backBuffer;	// Back-buffer used for rendering
	ID3D11Texture2D* depthStencil;	// Depth stencil
	ID3D11DepthStencilView* depthStencilView;	// View used to enable depth stencil

	// Shaders
	ID3D11VertexShader* vertexShader;	// Vertex shader
	ID3D11PixelShader* pixelShader;		// Pixel shader
	ID3D11InputLayout* vertexLayout;		// Vertex layout

	// Camera information
	ID3D11Buffer* constantBuffer;	// Constant buffer used to hold camera data

	// Clear color for screen
	D3DXCOLOR clearColor;
};

// Assign the proper function to a job, this gives a cleaner way of creating upper level engine jobs
void AssignRenderingFunction(Job& job);

// Request a frame render
void RequestRendering(Job& job);

// Wait for rendering to finish
void WaitForRendering(Job& job);


#include "SumRenderManager.inl"

// TEMP CODE!
static XMMATRIX world;
XMMATRIX& GetView(void);
static XMMATRIX projection;

#endif